package cn.yunhe;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.connection.RedisListCommands;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by zs on 2017/12/1.
 * 测试链表结构
 */
public class Demo6 {

    @Test
    public void testList() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);

        try {
            //删除链表，随时测试
            redisTemplate.delete("list");
            //node3插入链表list
            redisTemplate.opsForList().leftPush("list", "node3");

            List<String> nodeList = new ArrayList<String>();
            for (int i = 2; i >= 1; i--) {
                nodeList.add("node" + i);
            }

            //相当于lpush把多个值左插入链表
            redisTemplate.opsForList().leftPushAll("list", nodeList);
            //从右边插入一个节点
            redisTemplate.opsForList().rightPush("list", "node4");
            //获取下标为0的节点
            String node1 = (String) redisTemplate.opsForList().index("list", 0);
            //获取链表长度
            long size = redisTemplate.opsForList().size("list");
            //从左边弹出第一个节点
            String lpop = (String) redisTemplate.opsForList().leftPop("list");
            //从右边弹出第一个节点
            String rpop = (String) redisTemplate.opsForList().rightPop("list");

            //需要使用更底层的命令才能操作linsert命令
            //使用linsert在node2前插入一个节点
            redisTemplate.getConnectionFactory().getConnection().lInsert(
                    "list".getBytes("UTF-8"),
                    RedisListCommands.Position.BEFORE,
                    "node2".getBytes("UTF-8"), "before_node".getBytes("UTF-8"));
            //使用linsert在node2后插入一个节点
            redisTemplate.getConnectionFactory().getConnection().lInsert(
                    "list".getBytes("UTF-8"),
                    RedisListCommands.Position.AFTER,
                    "node2".getBytes("UTF-8"), "after_node".getBytes("UTF-8"));

            //判断list是否存在，如果存在就在左边插入head节点
            redisTemplate.opsForList().leftPushIfPresent("list", "head");
            //判断list是否存在，如果存在就在右边插入head节点
            redisTemplate.opsForList().rightPushIfPresent("list", "end");
            //从左到右，或者下标从0到10的节点元素
            List valueList = redisTemplate.opsForList().range("list", 0, 10);
            nodeList.clear();

            for (int i = 1; i <= 3; i++) {
                nodeList.add("node");
            }

            //在链表左边插入三个值为node的节点
            redisTemplate.opsForList().leftPushAll("list", nodeList);
            //从左到右删除至多三个node节点
            redisTemplate.opsForList().remove("list", 3, "node");
            //给链表下标为0的节点设置新值
            redisTemplate.opsForList().set("list", 0, "new_head_value");

        } catch (Exception e) {
            e.printStackTrace();
        }

        printList(redisTemplate, "list");
    }


    public static void printList(RedisTemplate redisTemplate, String key) {
        //链表长度
        Long size = redisTemplate.opsForList().size(key);
        //获取整个链表的值
        List valueList = redisTemplate.opsForList().range(key, 0, size);
        System.out.println(valueList); //[new_head_value, before_node, node2, after_node, node3, end]
    }

}
